package com.lvliucun.validate.anotation;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lvliucun.validate.check.ParamChecker;
import com.lvliucun.validate.utils.SpringUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description 参数校验工具类
 * @Author zhuojiajin
 * @Date 2020年8月14日13:53:15
 * @Version 1.0
 **/
@Aspect
@Component
public class ParamCheckUtil {
    @Pointcut("@annotation(com.lvliucun.validate.anotation.ParamCheck)")
    public void annotationPointCut() {
    }

    @Around("annotationPointCut() && @annotation(paramCheck)")
    public Object around(ProceedingJoinPoint joinPoint, ParamCheck paramCheck) throws Throwable{
        //获取参数
        JSONObject param = getNameAndValue(joinPoint);
        //获取注解中的校验规则
        String rule = paramCheck.value();

        String path = joinPoint.getTarget().getClass().getName() +":" +joinPoint.getSignature().getName();


        if(StringUtils.isEmpty(rule)){
            //未配置规则，方法继续
            return joinPoint.proceed();
        }else{
            String[] rules = rule.split(",");
            for(String ruleStr:rules){
                String[] rulePart = ruleStr.split(":");
                excuteCheck(param,rulePart[0],rulePart[1],path);
            }
            return joinPoint.proceed();
        }
    }



    /**
      * @Description 获取参数JSON
      * @Author zhuojiajin
      * @Param [joinPoint]
      * @Return com.alibaba.fastjson.JSONObject
      * @Date 2019/6/3 16:28
     **/
    private JSONObject getNameAndValue(ProceedingJoinPoint joinPoint) {
        Map<String, Object> param = new HashMap<String,Object>();

        //获取参数值数组
        Object[] paramValues = joinPoint.getArgs();
        //获取参数名数组
        String[] paramNames = ((CodeSignature)joinPoint.getSignature()).getParameterNames();


        //组装，返回jsonobject
        for (int i = 0; i < paramNames.length; i++) {
            if(!(paramValues[i] instanceof MultipartFile || paramValues[i] instanceof MultipartFile[])){
                param.put(paramNames[i], paramValues[i]);
            }else{
                if(paramValues[i] instanceof MultipartFile){
                    if(paramValues[i] != null && ((MultipartFile)paramValues[i]).getSize() != 0) {
                        param.put(paramNames[i], "存在文件");
                    }else{
                        param.put(paramNames[i], null);
                    }
                }else if(paramValues[i] instanceof MultipartFile[]){
                    if(paramValues[i] != null && ((MultipartFile[])paramValues[i]).length>0) {
                        param.put(paramNames[i], "存在文件");
                    }else{
                        param.put(paramNames[i], null);
                    }
                }
            }
        }

        return JSONObject.parseObject(JSON.toJSONString(param));
    }

    /**
      * @Description 执行参数校验
      * @Author zhuojiajin
      * @Param [args, filedName, className]
      * @Return boolean
      * @Date 2019/6/3 17:23
     **/
    public boolean excuteCheck(JSONObject args, String filedName,String className,String path) throws Exception{
        ParamChecker paramChecker = (ParamChecker) SpringUtil.getBean(className);
        return paramChecker.checkParam(args,filedName,path);
    }

    /**
     * @Description 解析规则
     * @Author zhuojiajin
     * @Date 2020/9/29 16:08
     * [rule]
     * @Return java.lang.String[]
     **/
    private String[] getRules(String rule){
        List<String> result = new ArrayList<String>();
        String[] rules = rule.split(",");
        for(String ruleStr:rules){
            String[] rulePart = ruleStr.split(":");
        }
        return null;
    }

}
